package com.gtja.beoms.utils;

import cn.hutool.http.HttpRequest;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gtja.beoms.base.CommonConstants;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * http请求的工具类
 */
@Component
public class HttpRequestUtil {

    private static Logger logger = LoggerFactory.getLogger(HttpRequestUtil.class);

    private static String proxyIp;

    private static int proxyHost;

    private static boolean proxyOnOff;

    @Value("${proxy_ip}")
    public void setProxyIp(String proxyIp) {
        HttpRequestUtil.proxyIp = proxyIp;
    }

    @Value("${proxy_host}")
    public void setProxyHost(String proxyHost) {
        HttpRequestUtil.proxyHost = Integer.parseInt(proxyHost);
    }

    @Value("${proxy_on_off}")
    public void setProxyOnOff(boolean proxyOnOff) {
        HttpRequestUtil.proxyOnOff = proxyOnOff;
    }


    /**
     * 设置代理
     */
    private static RequestConfig setProxy(String url) {
        RequestConfig requestConfig;
        // TODO 临时添加 后期考虑删除 BEGIN
        String targetUrl = "";
        if (!StringUtils.isEmpty(url)) {
            targetUrl = url.replace(CommonConstants.HTTP, "").replace(CommonConstants.HTTPS, "");
        }
        // TODO END
        // 是否开启代理
        if (proxyOnOff && !targetUrl.startsWith("10.")) {
            requestConfig = RequestConfig.custom()
                    .setProxy(new HttpHost(proxyIp, proxyHost))
                    .build();
        } else {
            requestConfig = RequestConfig.custom().build();
        }
        return requestConfig;
    }

    /**
     * 响应检查
     */
    private static String responseHandle(CloseableHttpClient httpClient,
                                         CloseableHttpResponse response,
                                         HttpEntity httpEntity) throws IOException {
        String result = null;
        //请求成功
        if (response.getStatusLine().getStatusCode() == 200) {
            HttpEntity entity = response.getEntity();
            result = EntityUtils.toString(entity, "utf-8");
        }
        //307是重定向返回码 需要再次请求
        if (response.getStatusLine().getStatusCode() == 307) {
            Header header = response.getFirstHeader("location"); // 跳转的目标地址是在 HTTP-HEAD上
            String newuri = header.getValue(); // 这就是跳转后的地址，再向这个地址发出新申请
            System.out.println(newuri);
            HttpPost newHttpPost = new HttpPost(newuri);
            newHttpPost.setConfig(setProxy(newuri));
            newHttpPost.addHeader("Content-Type", "application/json");
            newHttpPost.setEntity(httpEntity);
            response = httpClient.execute(newHttpPost);
            if (response.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = response.getEntity();
                result = EntityUtils.toString(entity, "utf-8");
            }
        }
        return result;
    }

    /**
     * post请求
     *
     * @param url
     * @param params
     * @param header
     * @return
     * @throws IOException
     */
    public static String httpPostForm(String url, Map<String, Object> params, Map<String, String> header) throws IOException {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String result = null;

        HttpPost httpPost = new HttpPost(url.trim());
        //设置代理
        httpPost.setConfig(setProxy(url));
        // 设置参数
        StringEntity httpEntity = new UrlEncodedFormEntity(map2NameValuePairList(params), "utf-8");
        httpPost.setEntity(httpEntity);
        // 设置Header
        if (header != null && !header.isEmpty()) {
            for (Iterator<Map.Entry<String, String>> it = header.entrySet().iterator(); it.hasNext(); ) {
                Map.Entry<String, String> entry = (Map.Entry<String, String>) it.next();
                httpPost.setHeader(new BasicHeader(entry.getKey(), entry.getValue()));
            }
        }

        CloseableHttpResponse response = null;
        try {
            //5.发送请求
            response = httpClient.execute(httpPost);
            //6.响应处理
            result = responseHandle(httpClient, response, httpEntity);
        } catch (UnsupportedEncodingException e) {
            logger.info("https--post请求异常[{}]", e);
        } catch (IOException e) {
            logger.info("https--post请求异常[{}]", e);
        } finally {
            //6.关闭资源
            if (null != response) {
                response.close();
            }
            if (null != httpClient) {
                httpClient.close();
            }
        }
        return result;
    }


    /**
     * post请求发送json类型
     *
     * @param url
     * @param params
     * @return
     * @throws JsonProcessingException
     */
    public static String httpPost(String url, Map<String, Object> params) throws IOException {
        String result = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //2.声明post请求
        HttpPost httpPost = new HttpPost(url);
        //设置代理
        httpPost.setConfig(setProxy(url));
        //3.设置请求类型
        httpPost.addHeader("Content-Type", "application/json");
        //4.添加参数
        String json = new ObjectMapper().writeValueAsString(params);
        StringEntity httpEntity = new StringEntity(json, "utf-8");
        CloseableHttpResponse response = null;
        try {
            httpPost.setEntity(httpEntity);
            //5.发送请求
            response = httpClient.execute(httpPost);
            //6.响应处理
            result = responseHandle(httpClient, response, httpEntity);
        } catch (UnsupportedEncodingException e) {
            logger.info("https--post请求异常[{}]", e);
        } catch (IOException e) {
            logger.info("https--post请求异常[{}]", e);
        } finally {
            //6.关闭资源
            if (null != response) {
                response.close();
            }
            if (null != httpClient) {
                httpClient.close();
            }
        }
        return result;
    }

    /**
     * get请求带参数
     *
     * @param url
     * @param params
     * @param header
     * @return
     * @throws Exception
     */
    public static String doGet(String url, Map<String, Object> params, Map<String, String> header) throws Exception {

        HttpGet httpGet = new HttpGet(url.trim());
        //设置代理
        httpGet.setConfig(setProxy(url));
        // 设置参数
        if (params != null && !params.isEmpty()) {
            String str = EntityUtils.toString(new UrlEncodedFormEntity(map2NameValuePairList(params), "utf-8"));
            String uri = httpGet.getURI().toString();
            if (uri.indexOf("?") >= 0) {
                httpGet.setURI(new URI(httpGet.getURI().toString() + "&" + str));
            } else {
                httpGet.setURI(new URI(httpGet.getURI().toString() + "?" + str));
            }
        }
        // 设置Header
        if (header != null && !header.isEmpty()) {
            for (Iterator<Map.Entry<String, String>> it = header.entrySet().iterator(); it.hasNext(); ) {
                Map.Entry<String, String> entry = (Map.Entry<String, String>) it.next();
                httpGet.setHeader(new BasicHeader(entry.getKey(), entry.getValue()));
            }
        }
        String body = execute(httpGet);
        return body;
    }

    /**
     * post的请求不带参数
     *
     * @param url
     * @return
     * @throws IOException
     */
    public static String httpPost(String url) throws IOException {
        String result = null;
        //1、创建HttpClient连接
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //2.声明post请求
        HttpPost httpPost = new HttpPost(url);
        //设置代理
        httpPost.setConfig(setProxy(url));
        CloseableHttpResponse response = null;
        try {
            //5.发送请求
            response = httpClient.execute(httpPost);
            //6.响应处理
            result = responseHandle(httpClient, response, null);
        } catch (UnsupportedEncodingException e) {
            logger.info("https--post请求异常[{}]", e);
        } catch (IOException e) {
            logger.info("https--post请求异常[{}]", e);
        } finally {
            //6.关闭资源
            if (null != response) {
                response.close();
            }
            if (null != httpClient) {
                httpClient.close();
            }
        }
        return result;
    }

    /**
     * get请求
     *
     * @param url
     * @return
     */
    public static String httpGet(String url) {
        String context = null;
        //1、创建HttpClient连接
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //2、创建HtpGet请求
        HttpGet httpGet = new HttpGet(url);
        //设置代理
        httpGet.setConfig(setProxy(url));
        //3、HttpClient发送请求
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(httpGet);
            //4、拿到请求页面的返回数据,请求成功才有数据啊！
            context = responseHandle(httpClient, response, null);
        } catch (IOException e) {
            logger.info("http请求get请求异常", e);
            //发送请求异常
        } finally {
            //不管如何关闭响应、请求的连接
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (httpClient != null) {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return context;
    }


    private static List<NameValuePair> map2NameValuePairList(Map<String, Object> params) {
        if (params != null && !params.isEmpty()) {
            List<NameValuePair> list = new ArrayList<NameValuePair>();
            Iterator<String> it = params.keySet().iterator();
            while (it.hasNext()) {
                String key = it.next();
                if (params.get(key) != null) {
                    String value = String.valueOf(params.get(key));
                    list.add(new BasicNameValuePair(key, value));
                }
            }
            return list;
        }
        return null;
    }

    private static String execute(HttpRequestBase requestBase) throws Exception {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        String body = null;
        try {
            CloseableHttpResponse response = httpclient.execute(requestBase);
            try {
                HttpEntity entity = response.getEntity();

                if (entity != null) {
                    body = EntityUtils.toString(entity, "utf-8");
                }
                EntityUtils.consume(entity);
            } catch (Exception e) {
                throw e;
            } finally {
                response.close();
            }
        } catch (Exception e) {
            throw e;
        } finally {
            httpclient.close();
        }
        return body;
    }

    /**
     * post请求,发送文件
     *
     * @param url
     * @param multipartFile
     * @param header
     * @return
     * @throws IOException
     */
    public static String httpPostFile(String url, MultipartFile multipartFile, Map<String, String> header) throws IOException {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String result = null;

        HttpPost httpPost = new HttpPost(url.trim());
        //设置代理
        httpPost.setConfig(setProxy(url));
        // 设置参数
//        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
//        builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
//        builder.addBinaryBody("name=\"file\"; filename="+multipartFile.getOriginalFilename(), multipartFile.getBytes());//添加文件
////        builder.addTextBody("Language", "9");  //添加文本类型参数
//        httpPost.setEntity(builder.build());
        MultipartEntity entity1 = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
        entity1.addPart("file", new ByteArrayBody(multipartFile.getBytes(), multipartFile.getContentType(), multipartFile.getName()));
        httpPost.setEntity(entity1);
        // 设置Header
        if (header != null && !header.isEmpty()) {
            for (Iterator<Map.Entry<String, String>> it = header.entrySet().iterator(); it.hasNext(); ) {
                Map.Entry<String, String> entry = (Map.Entry<String, String>) it.next();
                httpPost.setHeader(new BasicHeader(entry.getKey(), entry.getValue()));
            }
        }

        CloseableHttpResponse response = null;
        try {
            //5.发送请求
            response = httpClient.execute(httpPost);
            //6.响应处理
            result = responseHandle(httpClient, response, entity1);
        } catch (UnsupportedEncodingException e) {
            logger.info("https--post请求异常[{}]", e);
        } catch (IOException e) {
            logger.info("https--post请求异常[{}]", e);
        } finally {
            //6.关闭资源
            if (null != response) {
                response.close();
            }
            if (null != httpClient) {
                httpClient.close();
            }
        }
        return result;
    }

    public static String huToolPost(String url, Map<String, Object> params) {
        HttpRequest post = HttpRequest.post(url);
        if (!StringUtils.isEmpty(url)) {
            String cutUrl = url.replace(CommonConstants.HTTP, "").replace(CommonConstants.HTTPS, "");
            if (proxyOnOff && !cutUrl.startsWith("10.")) {
                post.setHttpProxy(proxyIp, proxyHost);
            }
        }
        return post.form(params)
                .execute()
                .body();
    }

}
